from eshop.lib.database import * 
from pylons import config
from sqlalchemy import Column, MetaData, Table, types, UniqueConstraint
from sqlalchemy.orm import mapper, relation
from sqlalchemy.orm import scoped_session, sessionmaker
from elixir import Unicode, DateTime, String, Integer, PickleType
from elixir import Entity, has_field, using_options, using_table_options
from elixir import has_many, belongs_to, has_and_belongs_to_many, has_one
from elixir.ext.encrypted import acts_as_encrypted
import sqlalchemy.types as types
from cPickle import *
import forms

# Global session manager.  Session() returns the session object appropriate for the current web request.
#Session = scoped_session(sessionmaker(autoflush=True, transactional=True, bind=config['pylons.g'].sa_engine))


# Global metadata. If you have multiple databases with overlapping table names, you'll need a metadata for each
# database.
#metadata = MetaData()


class ProductCategory(Entity):
    has_field('name', Unicode(50), required=True)
    has_field('description', Unicode(255))
    
    belongs_to('parent_category', of_kind='ProductCategory')
    has_many('child_categories', of_kind='ProductCategory')
    has_and_belongs_to_many('properties', of_kind='ProductProperty', inverse='categories', tablename='product_category_property')
    using_options(tablename='product_category', order_by='name')

class ProductProperty(Entity):
    (TYPE_STRING, TYPE_INT, TYPE_FLOAT, TYPE_DATE, TYPE_BOOLEAN) = range(5)
    has_field('code', Unicode(50), primary_key=True)
    has_field('description', Unicode(255))
    has_field('data_type', Integer, default=TYPE_STRING)
    has_many('products', of_kind='Product', inverse='category')
    has_and_belongs_to_many('categories', of_kind='ProductCategory', inverse='properties', tablename='product_category_property')
    using_options(tablename='product_property')

class Product(Entity):
    has_field('name', Unicode(255), required=True)
    has_field('url_mapping', Unicode(255), required=True)
    has_field('description', Unicode(255))
    has_field('properties', PickleType, default={})
    belongs_to('brand', of_kind='Brand')
    belongs_to('category', of_kind='ProductCategory')
    belongs_to('main_image', of_kind='Image')
    belongs_to('root_comment', of_kind='Comment')
    using_options(tablename='product', order_by='name')
    using_table_options(UniqueConstraint('url_mapping'))

class Brand(Entity):
    has_field('name', Unicode(255), required=True)
    has_many('products', of_kind='Product')
    using_options(tablename='brand', order_by='name')
    
class Comment(Entity):
    has_field('author_name', Unicode)
    has_field('text', Unicode)
    has_field('author_ip', Unicode)
    has_field('created', DateTime)
    belongs_to('parent_comment', of_kind='Comment')
    has_many('child_comments', of_kind='Comment')
    using_options(tablename='comment')
    
#class User(Entity):
#    has_field('login', Unicode(255), required=True)
#    has_field('password', Unicode(255), required=True)
#    has_field('email', Unicode(255), required=True)
#    has_field('full_name', Unicode(255), required=True)
#    has_and_belongs_to_many('roles', of_kind='UserRole')
#    using_options(tablename='user', order_by='login')
#
#    
#class UserRole(Entity):
#    has_field('name', Unicode(255), required=True)
#    has_field('description', Unicode(255))
#    using_options(tablename='user_role', order_by='name')

class User(Entity):
    has_field("uid", Integer, primary_key=True)
    has_field("username", Unicode(255), unique=True, nullable=False)
    has_field("email", Unicode(255), unique=True)
    has_field("password", Unicode)
    belongs_to('group', of_kind='Group', colname='group_uid')
    has_and_belongs_to_many('roles', of_kind='Role', tablename='users_roles')
    using_options(tablename='users')
    acts_as_encrypted(for_fields=['password'], with_secret='eshopsecretstringantyhack')

    def _repr_(self):
        return "User(%(username)s)" % self._dict_

class Group(Entity):
    has_field('uid', Integer, primary_key=True)
    has_field("name", String(255), unique=True, nullable=False)
    using_options(tablename='groups')

    def _repr_(self):
        return "Group(%(name)s)" % self._dict_

class Role(Entity):
    has_field("uid", Integer, primary_key=True)
    has_field("name", String(255), unique=True, nullable=False)
    using_options(tablename='roles')

#class UserRole(Entity):
#    belongs_to('user', of_kind='User', colname="user_uid")
#    belongs_to('role', of_kind='Role', colname="role_uid")
#    using_options(tablename='users_roles')


class Image(Entity):
    has_field('file_name', Unicode(255), required=True)
    using_options(tablename='image')
    
 
class Company(Entity):
    has_field('name', Unicode(255), required=True)
    has_field('phones', Unicode(1000), required=True)
    has_field('city', Unicode(255), required=True)
    has_field('address', Unicode(1000), required=True)
    has_field('working_hours', Unicode(1000), required=True)
    has_field('email', Unicode(255), required=True)
    has_field('site_url', Unicode(1000), required=True)
    has_one('price_list', of_kind='PriceList', inverse='company')
    using_options(tablename='company', order_by='name')

class PriceList(Entity):
    belongs_to('company', of_kind='Company')
    has_field('publish_date', DateTime, required=True)
    has_many('price_items', of_kind='PriceItem', inverse='price_list')
    using_options(tablename='price_list', order_by='publish_date')

class PriceItem(Entity):
    belongs_to('price_list', of_kind='PriceList', required=True)
    has_field('name', Unicode(4000), required=True)
    belongs_to('product', of_kind='Product')
    has_field('price', Integer, required=True)
    using_options(tablename='price_item')
   

#print "Creating tables"
#metadata.create_all(bind=config['pylons.g'].sa_engine)
#print "Successfully setup"    
    
## Define a table.
#table1 = table("table1", metadata, 
#    Column("id", types.Integer, primary_key=True),
#    Column("name", types.String, nullable=False),
#    )
#
## Define another table, reading its structure from an existing database table.
## You must provide an engine in this case.
#table2 = table("table2", metadata, autoload=True,
#    autoload_with=pylons.config['pylons.g'].sa_engine)
#
## Define ORM classes (often called "mapped classes").
#class MyClass(object):
#    pass
#
## Map each class to its corresponding table.  
#mapper(MyClass, table1)
#
## If you prefer 'assign_mapper'-like behavior, use this mapping syntax instead.
## See "Associating Classes and Mappers with a Contextual session" in the SQLAlchemy manual.
#Session.mapper(MyClass, table1)